﻿namespace AlgoHero.Modelo
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Collections;

    public class Nota
    {
        #region Atributos

        private string nombre;
        private int duracion;
        private double frecuencia;

        #endregion

        #region Constructor

        public Nota(string nombre, int duracion)
        {
            /* Precondiciónes: nombre debe un nombre nota musical válido.
             * duracion debe ser la duración musical que corresponde a la nota musical.
             */

            //Validacion de la duracion
            Duracion[] duraciones = (Duracion[])Enum.GetValues(typeof(Duracion));
            List<Duracion> lista_duraciones = new List<Duracion>(duraciones);

            if(!lista_duraciones.Contains((Duracion)duracion))
            {
                throw new ArgumentException("Duracion de nota inválida.");
            }

            this.duracion = duracion;

            //Lanza ArgumentException si el nombre no es correcto
            this.frecuencia = this.CalcularFrecuencia(nombre);
            this.nombre = nombre.ToUpper();                  
        }

        #endregion

        #region Métodos

        private double CalcularFrecuencia(string nombre)
        {
            /* Precondición: nombre debe ser el nombre de una nota musical válida.
             * Postcondición: Devuelve la frecuencia de la nota ingresada.
             * Caso contrario, si la nota es inválida, se lanza una excepción ArgumentException.
             */
            string[] Nombres = { "DO", "DO#", "RE", "RE#", "MI", "FA", "FA#", "SOL", "SOL#", "LA", "LA#", "SI", "SILENCIO" };
            double[] Frecuencias = { 261.63, 277.18, 293.66, 311.13, 329.63, 349.23, 369.99, 392.00, 415.3, 440, 466.16, 493.88, 0.0 };
            List<string> lstNombres = new List<string>(Nombres);

            if (lstNombres.LastIndexOf(nombre.ToUpper()) != -1)
            {
                return Frecuencias[lstNombres.IndexOf(nombre.ToUpper())];
            }
            else
            {
                throw new ArgumentException("La nota ingresada es inválida");
            }
        }
        
        public override bool Equals(object obj) 
        {
            Nota otraNota;

            try
            {
                otraNota = (Nota)obj;
                return (this == otraNota);
            }
            catch
            {
                return false;
            }
        }

        public static bool operator ==(Nota unaNota, Nota otraNota)
        {
            return ((unaNota.Frecuencia == otraNota.Frecuencia) && (unaNota.Duracion == otraNota.Duracion)
                     && (unaNota.Nombre == otraNota.Nombre));
        }
        public static bool operator !=(Nota unaNota, Nota otraNota)
        {
            return !(unaNota == otraNota);
        }
        
        #endregion

        #region Propiedades

        public string Nombre
        {
            get { return this.nombre; }
        }

        public int Duracion
        {
            get { return this.duracion; }
        }

        public double Frecuencia
        {
            get { return this.frecuencia; }
        }

        #endregion
    }
}

